﻿module TokensTests

open System
open System.IO
open Microsoft.VisualStudio.TestTools.UnitTesting
open Utility
open Streams
open Tokens
open Steps

[<TestClass>]
type public TokensTests() = 

   [<TestMethod>]
   member public self.ToString_ReturnsTokensSourcesWithSpaces() =
      use stream = CreateStream("Given: This is a test")
      use reader = CreateReader(stream)

      let actual = ReadStep(reader, StepKind.Given ).Value.Instructions |> ToString

      Assert.AreEqual("This is a test", actual)


   [<TestMethod>]
   member public self.ReadToken_SkipsIrrelevantTextAndReadsUntilWhitespace() =
      use stream = CreateStream(" {comment #1{comment #2}}TEST ")
      use reader = CreateReader(stream)

      let actual = ReadToken(reader).Value

      Assert.AreEqual("TEST", actual.Source)


   [<TestMethod>]
   member public self.ReadToken_SkipsIrrelevantTextAndReadsUntilComment() =
      use stream = CreateStream(" {comment #1{comment #2}}\"TEST\"{")
      use reader = CreateReader(stream)

      let actual = ReadToken(reader).Value

      Assert.AreEqual("\"TEST\"", actual.Source)


   [<TestMethod>]
   member public self.ReadToken_SkipsIrrelevantTextAndReadsUntilPeriod() =
      use stream = CreateStream(" {comment #1{comment #2}}`TEST`.")
      use reader = CreateReader(stream)

      let actual = ReadToken(reader).Value

      Assert.AreEqual("`TEST`", actual.Source)


   [<TestMethod>]
   member public self.ReadToken_BasicParsingTest() =
      use stream = CreateStream(@"""This"" {
         comment #1 { comment #2 }
         } 
         is 
          a `test`"
         )
      use reader = CreateReader(stream)

      let _this = ReadToken(reader).Value
      let _is = ReadToken(reader).Value
      let _a = ReadToken(reader).Value
      let _test = ReadToken(reader).Value

      Assert.IsTrue(_this.IsBoxed)
      Assert.AreEqual(1, _this.Location.Line)
      Assert.AreEqual(1, _this.Location.Column)
      Assert.AreEqual(1, _this.Location.Index)
      Assert.AreEqual("\"This\"", _this.Source)

      Assert.IsFalse(_is.IsBoxed)
      Assert.AreEqual(4, _is.Location.Line)
      Assert.AreEqual(10, _is.Location.Column)
      Assert.AreEqual(69, _is.Location.Index)
      Assert.AreEqual("is", _is.Source)

      Assert.IsFalse(_a.IsBoxed)
      Assert.AreEqual(5, _a.Location.Line)
      Assert.AreEqual(11, _a.Location.Column)
      Assert.AreEqual(84, _a.Location.Index)
      Assert.AreEqual("a", _a.Source)

      Assert.IsTrue(_test.IsBoxed)
      Assert.AreEqual(5, _test.Location.Line)
      Assert.AreEqual(13, _test.Location.Column)      
      Assert.AreEqual(86, _test.Location.Index)
      Assert.AreEqual("`test`", _test.Source)


   [<TestMethod>]
   member public self.ReadDescription_ReadsEntireDescriptionAsASingleToken() =
      use stream = CreateStream(" This \t is \r\n a \r\n test \r\n\r\n ")
      use reader = CreateReader(stream)

      let actual = ReadDescription(reader).Value

      Assert.AreEqual("This \t is \r\n a \r\n test ", actual.Source)


   [<TestMethod>]
   member public self.ReadDescription_RecognizeDoubleCRLFEndings() =
      use stream = CreateStream(" This \t is \r\n a \r\n test \r\n\r\n ")
      use reader = CreateReader(stream)

      let actual = ReadDescription(reader).Value

      Assert.AreEqual("This \t is \r\n a \r\n test ", actual.Source)


   [<TestMethod>]
   member public self.ReadDescription_LeavesOutComments() =
      let expected = "This {is {a}} test \r\n\r\n"

      use stream = CreateStream(expected)
      use reader = CreateReader(stream)

      let actual = ReadDescription(reader).Value

      Assert.AreEqual("This  test ", actual.Source)


